package org.tgcloud.group.core;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * Created by cloudLiu on 2015/9/9.
 */
@Component
public class HttpClientUtil extends BaseLogger {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    public static final int CONNECT_TIMEOUT = 10 * 1000;

    public static final Charset UTF_8 = Charset.forName("UTF-8");

    private PoolingHttpClientConnectionManager manager;

    public CloseableHttpClient client;

    public HttpClientUtil()
    {
        manager = new PoolingHttpClientConnectionManager();
        /*最大连接数*/
        manager.setMaxTotal(200);
        /*将每个路由基础的连接数增加到20*/
        manager.setDefaultMaxPerRoute(20);
        client = HttpClients.custom().setConnectionManager(manager).build();

    }

    /**
     * 发送get请求
     * @param params
     */
    public String doGet(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.GET, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    /**
     * 发送post请求
     * @param url
     * @param params
     * @return
     */
    public String doPost(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.POST, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    public String doPostJsonMJShop(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.POSTJSONMJSHOP, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    public String doGetMJShop(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.GETMJSHOP, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    public String doPostJson2(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.POSTJSON2, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    public String doPostJson(String url, Map params)
    {
        final String[] result_ = new String[]{null};
        doRequest(RequestMethod.POSTJSON, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    public void doRequest(final RequestMethod method, final String url, final Map<String,Object> params, final List<File> fileList, ResponseBack callBack)
    {
        if (Strings.isNullOrEmpty(url)) {
            logger.warn("没有请求路径");
            return;
        }
        boolean hasCallBack = false;
        if (callBack != null)
        {
            hasCallBack  = true;
        }
        HttpUriRequest request = null;
        switch (method)
        {
            case GET:
                String getUrl = url;
                /*拼装请求参数*/
                if (params != null)
                {
                    StringBuilder sb = new StringBuilder("");
                    for (String key : params.keySet())
                    {
                        sb.append(key + "=" + params.get(key) + "&");
                    }
                    getUrl += "?" + sb.toString();
                }

                request = new HttpGet(getUrl);
                break ;
            case POSTJSON2:
                request = new HttpPost(url);
                request.addHeader("Content-Type", "application/json;charset=utf-8");
                if (params != null)
                {
//                    JSONObject jsonString = new JSONObject(params);
                    try {
                        StringEntity entity = new StringEntity(params.toString());
//                        entity = new UrlEncodedFormEntity(pairs,"utf-8");
                        ((HttpPost)request).setEntity(entity);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                break;
            case POSTJSONMJSHOP:
                request = new HttpPost(url);
                request.addHeader("Content-Type", "application/json;charset=utf-8");
                request.addHeader("tenant-id", "162");
                if (params != null)
                {
                    try {
                        StringEntity entity = new StringEntity(new JSONObject(params).toString(), "UTF-8");
                        ((HttpPost)request).setEntity(entity);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                break;
            case GETMJSHOP:
                String getMJShopUrl = url;
                /*拼装请求参数*/
                if (params != null)
                {
                    StringBuilder sb = new StringBuilder("");
                    for (String key : params.keySet())
                    {
                        sb.append(key + "=" + params.get(key) + "&");
                    }
                    getMJShopUrl += "?" + sb.toString();
                }
                request = new HttpGet(getMJShopUrl);
                request.addHeader("tenant-id", "162");
                break ;
            case POSTJSON:
                request = new HttpPost(url);
                request.addHeader("Content-Type", "application/json;charset=utf-8");
                if (params != null)
                {
                    JSONObject jsonString = new JSONObject(params);
                    try {
                        StringEntity entity = new StringEntity(jsonString.toString());
                        ((HttpPost)request).setEntity(entity);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                break;
            case POST:
                request = new HttpPost(url);
                request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
                if (params != null)
                {
                    List<NameValuePair> pairs = Lists.newArrayList();
                    for (String key : params.keySet())
                    {
                        pairs.add(new BasicNameValuePair(key, (String)params.get(key)));
                    }
                    UrlEncodedFormEntity entity= null;
                    try {
                        entity = new UrlEncodedFormEntity(pairs,"utf-8");
                        ((HttpPost)request).setEntity(entity);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                logger.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }

        CloseableHttpResponse response = null;
        try {
            response = client.execute(request);
            if (hasCallBack)
            {
                callBack.onResponse(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(),UTF_8));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
//            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }


    }

    public interface ResponseCallback {
        /**
         * 响应后回调方法
         */
        void onResponse();
    }

    /**
     * 标识HTTP请求类型枚举
     *
     * @author peiyu
     * @since 1.0
     */
    static enum RequestMethod {
        /**
         * HTTP GET请求
         * 一般对应的是查询业务接口
         */
        GET,
        /**
         * HTTP POST请求
         * 一般对应的是新增业务接口
         * 只是一般都通用这个请求方式来处理一切接口了T_T
         */
        POST,
        POSTJSON,
        POSTJSON2,
        POSTJSONMJSHOP,
        GETMJSHOP,
        /**
         * HTTP PUT请求，用的太少，暂不支持
         * 一般对应的是更新业务接口
         */
        PUT,
        /**
         * HTTP DELETE请求，用的太少，暂不支持
         * 一般对应的是删除业务接口
         */
        DELETE
    }

    public interface ResponseBack
    {
        void onResponse(int resultCode, String result);
    }

    /**
     * 请求星榜数据
     * @param params
     */
    public String doStarGet(String url, Map params, String cookie)
    {
        final String[] result_ = new String[]{null};
        doStarRequest(RequestMethod.GET, url, params, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        }, cookie);
        return result_[0];
    }

    public void doStarRequest(final RequestMethod method, final String url, final Map<String,Object> params, final List<File> fileList, ResponseBack callBack, String cookie)
    {
        if (Strings.isNullOrEmpty(url)) {
            logger.warn("没有请求路径");
            return;
        }
        boolean hasCallBack = false;
        if (callBack != null)
        {
            hasCallBack  = true;
        }
        HttpUriRequest request = null;
        switch (method)
        {
            case GET:
                String getUrl = url;
                /*拼装请求参数*/
                if (params != null)
                {
                    StringBuilder sb = new StringBuilder("");
                    for (String key : params.keySet())
                    {
                        sb.append(key + "=" + params.get(key) + "&");
                    }
                    getUrl += "?" + sb.toString();
                }

                request = new HttpGet(getUrl);
                request.setHeader("Cookie", cookie);
                break ;
            case POST:
                request = new HttpPost(url);
                if (params != null)
                {
                    List<NameValuePair> pairs = Lists.newArrayList();
                    for (String key : params.keySet())
                    {
                        pairs.add(new BasicNameValuePair(key, (String)params.get(key)));
                    }
                    UrlEncodedFormEntity entity= null;
                    try {
                        entity = new UrlEncodedFormEntity(pairs,"utf-8");
                        ((HttpPost)request).setEntity(entity);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                logger.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }

        CloseableHttpResponse response = null;
        try {
            response = client.execute(request);
            if (hasCallBack)
            {
                callBack.onResponse(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(),UTF_8));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
//            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }


    }

    /**
     *
     *  xml参数
     * @param
     */
    public String doPostXML(String url, String xml) {
        final String[] result_ = new String[]{null};
        doRequestXML(RequestMethod.POST, url, xml, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        });
        return result_[0];
    }

    /**
     * @return
     * @Author SGY
     * @Date 2019/9/5 15:04
     * @Param
     * @Description
     **/
    public void doRequestXML(final RequestMethod method, final String url, final String xml, final List<File> fileList, ResponseBack callBack) {
        if (Strings.isNullOrEmpty(url)) {
            logger.warn("没有请求路径");
            return;
        }
        boolean hasCallBack = false;
        if (callBack != null) {
            hasCallBack = true;
        }
        HttpUriRequest request = null;
        switch (method) {
//            case GET:
//                String getUrl = url;
//                /*拼装请求参数*/
//                if (params != null) {
//                    StringBuilder sb = new StringBuilder("");
//                    for (String key : params.keySet()) {
//                        sb.append(key + "=" + params.get(key) + "&");
//                    }
//                    getUrl += "?" + sb.toString();
//                }
//
//                request = new HttpGet(getUrl);
//                break;
            case POST:
                request = new HttpPost(url);
                request.addHeader("Content-Type","text/xml");
//                request.addHeader("charset","utf-8");
                // 得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
                StringEntity postEntity = new StringEntity(xml, "UTF-8");
                ((HttpPost) request).setEntity(postEntity);
                //                }
                break;
            case PUT:
            case DELETE:
            default:
                logger.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }

        CloseableHttpResponse response = null;
        try {
            response = client.execute(request);
            if (hasCallBack) {
                callBack.onResponse(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(), UTF_8));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
//            HttpClientUtils.closeQuietly(client);
            logger.info("结果7：" + response + "===1==="+ request);
            HttpClientUtils.closeQuietly(response);
        }
    }


    public String doImPost(String url, Map<String, String> headers, Map body)
    {
        final String[] result_ = new String[]{null};
        doImRequest(RequestMethod.POST, url, headers, body, null, new ResponseBack() {
            @Override
            public void onResponse(int resultCode, String result) {
                result_[0] = result;
            }
        }, null);
        return result_[0];
    }

    private void doImRequest(final RequestMethod method, final String url, Map<String, String> headers, final Map body, final List<File> fileList, ResponseBack callBack, String cookie)
    {
        if (Strings.isNullOrEmpty(url)) {
            logger.warn("没有请求路径");
            return;
        }
        boolean hasCallBack = false;
        if (callBack != null)
        {
            hasCallBack  = true;
        }
        HttpUriRequest request = null;
        switch (method)
        {
            case GET:
                break ;
            case POST:
                request = new HttpPost(url);
                if (body != null)
                {
                    if (headers != null && !headers.isEmpty())
                    {
                        for (Map.Entry<String, String> e : headers.entrySet()) {
                            request.addHeader(e.getKey(), e.getValue());
                        }
                        System.out.println("header-"+JSON.toJSONString(headers));
                    }
                    System.out.println("body-"+JSON.toJSONString(body));
                    StringEntity entity= null;
                    try {
                        entity = new StringEntity(JSON.toJSONString(body), "utf-8");
//                        entity = new StringEntity(JSON.toJSONString(body), "utf-8");
                        entity.setContentType("application/json");
//                        entity.setContentType("application/x-www-form-urlencoded");
                        ((HttpPost)request).setEntity(entity);
                    } catch (Exception e) {
                        printErrorInfo(e);
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                logger.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }

        CloseableHttpResponse response = null;
        try {
            response = client.execute(request);
            if (hasCallBack)
            {
                callBack.onResponse(response.getStatusLine().getStatusCode(), EntityUtils.toString(response.getEntity(),UTF_8));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
//            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }


    }
}
